﻿using LxBasic;
using System;

namespace LxCore
{
    public class CalcManage
    {
        protected LxSim Sim => LxSim.Sim;
        protected void runCommon(Action action)
        {
            MultiThreads.RunHostTask(() =>
            {
                if (Sim.Scheduler.SetRunningState(RunningStates.Running))
                {
                    action.Invoke();
                    Sim.Scheduler.SetRunningState(RunningStates.Idle);
                }
            });
        }
        public void ClearSolution()
        {
            if (Sim.Scheduler.SetRunningState(RunningStates.Running))
            {
                Sim.Fields.ClearFields();
                Sim.Solvers.ClearSolver();
                Sim.Monitors.ClearHistory();
                Sim.Visuals.ClearHistory();
                Sim.Steps.ClearHistory();
                Sim.Scheduler.SetRunningState(RunningStates.Idle);
            }
        }
        public void RunInitialization()
        {
            runCommon(resetSolverAndInit);
        }
        public void RunSimulation()
        {
            runCommon(() =>
            {
                resetSolverAndInit();
                runSimulation();
            });
        }
        public void RunSimulationOneStep()
        {
            runCommon(() =>
            {
                resetSolverAndInit();
                runSimulationOneStep();
            });
        }
        protected void resetSolverAndInit()
        {
            Sim.Mesh.CheckCreate();
            //创建场、求解器等
            Sim.Fields.CheckCreate();
            Sim.Solvers.CheckCreate();
            Sim.Monitors.CheckCreate();
            //fields初始化
            Sim.Solvers.Initialize();
        }
        private bool isInterrupt { get => Sim.Scheduler.IsInterrupting; }
        protected void runSimulation()
        {
            for (; ; )
            {
                bool finished = runSimulationOneStep();
                if (finished || isInterrupt) return;
            }
        }
        protected bool runSimulationOneStep()
        {
            switch (Sim.Physics.TimeDiscreteType)
            {
                default:
                case TimeDiscreteTypes.Steady:
                    return runOneStep_Steady();
                case TimeDiscreteTypes.Implicit_1st:
                case TimeDiscreteTypes.Implicit_2nd:
                    return runOneStep_TransImplicit();
                case TimeDiscreteTypes.Explicit_1st:
                case TimeDiscreteTypes.Explicit_2nd:
                    return runOneStep_TransExplicit();
            }
        }
        protected bool runOneStep_Steady()
        {
            Sim.Steps.IterationStep.StepStart();
            Sim.Solvers.Solve_Steady();
            Sim.Monitors.RunMonitors_Steady();
            Sim.Steps.IterationStep.StepEnd();
            return Sim.Steps.IterationStep.IsStop();
        }
        protected bool runOneStep_TransExplicit()
        {
            Sim.Steps.TimeStep.StepStart();
            Sim.Solvers.Solve_ExplicitTrans();
            Sim.Solvers.SaveOldValue();
            Sim.Monitors.RunMonitors_Transient();
            Sim.Steps.TimeStep.StepEnd();
            return Sim.Steps.TimeStep.IsStop();
        }
        protected bool runOneStep_TransImplicit()
        {
            if (!Sim.Steps.TimeStep.CurrentStepOngoing)//如果之前瞬态未成功结束，需要跳过这一步
            {
                Sim.Steps.TimeStep.StepStart();
            }
            for (; ; )
            {
                Sim.Steps.IterationStep.StepStart();
                Sim.Solvers.Solve_ImplicitTrans();
                Sim.Monitors.RunMonitors_Steady();
                Sim.Steps.IterationStep.StepEnd();
                if (Sim.Steps.IterationStep.IsStop()) break;
                if (isInterrupt) return false;
            }
            Sim.Solvers.SaveOldValue();
            Sim.Monitors.RunMonitors_Transient();
            Sim.Steps.TimeStep.StepEnd();
            return Sim.Steps.TimeStep.IsStop();
        }
    }
}
